#ifndef MOCHA_DETAIL_COLOR_HPP_INCLUDED
#define MOCHA_DETAIL_COLOR_HPP_INCLUDED

/**
 * @file
 */

#include <cstddef>
#include <cstdint>
#include "mocha/color.h"
#include "mocha/enum_string.hpp"
#include "mocha/memory.hpp"

namespace mocha { namespace graphics {
using ::mocha_rgba_channel_t;
using ::mocha_rgba_t;
using ::mocha_pixel_data_type;
typedef ::mocha_rgba_channel_t rgba_channel_t;
typedef ::mocha_rgba_t rgba_t;
typedef mocha_pixel_data_type pixel_data_type;
const rgba_t color_white = 0xFFFFFFFF;
const rgba_t color_white_alpha = 0xFFFFFF00;
const rgba_t color_black = 0x000000FF;
const rgba_t color_black_alpha = 0x00000000;
const rgba_t color_red = 0xFF0000FF;
const rgba_t color_green = 0x00FF00FF;
const rgba_t color_blue = 0x0000FFFF;
/**
 * 32-bit RGBA color.
 * Provides access to individual channels via multiple views (members).
 * Implicitly assigns/converts to a vanilla unsigned 32-bit integer.
 */
struct MOCHA_PACKED color {
	color(): value(color_black) {}
	color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha = 0xFF): red(red), green(green), blue(blue), alpha(alpha) {}
	color(std::uint32_t value): value(value) {}
	std::uint32_t& operator=(std::uint32_t& value) {
		return this->value = value;
	}
	operator std::uint32_t() const {
		return value;
	}
	union {
		struct MOCHA_PACKED {
			std::uint8_t red, green, blue, alpha;
		};
		std::uint8_t channels[4];
		std::uint32_t value;
	};
};
/**
 * Pixel channel mask, indicating where channel values are found within an aggregate pixel value.
 * For integer channels, the masks are used to denote the size, order, and position of channel values within a pixel value.
 * For floating point channels, the masks are used as integer indecies, indicating the order and positions of each value.
 * Absent floating point channels are indicated with a -1 value, which is why the mask type is signed.
 * Naturally, absent integer channels are indicated with a 0 since this is an empty mask and will reveal no bits for that channel.
 */
struct pixel_channel_mask {
	std::int32_t red, green, blue, alpha;
};
/**
 *
 * @see pixel_channel_mask
 * @see pixel_data_type
 */
struct pixel_format {
	pixel_channel_mask mask;
	pixel_data_type type;
	//color key;
};
/**
 * @param format Pixel format.
 * @return Bytes per pixel.
 */
inline size_t bytes_per_pixel(const pixel_format& format) {
	return 4u; // FIXME: Base the size on the number and size of channels in the pixel format.
}
}}
MOCHA_ENUM_STRING_BEGIN(mocha::graphics::pixel_data_type) {
	MOCHA_ENUM_STRING(mocha_pixel_byte);
	MOCHA_ENUM_STRING(mocha_pixel_ubyte);
	MOCHA_ENUM_STRING(mocha_pixel_int);
	MOCHA_ENUM_STRING(mocha_pixel_uint);
	MOCHA_ENUM_STRING(mocha_pixel_float);
	MOCHA_ENUM_STRING(mocha_pixel_double);
	MOCHA_ENUM_ALIAS(mocha_pixel_byte, "byte");
	MOCHA_ENUM_ALIAS(mocha_pixel_ubyte, "ubyte");
	MOCHA_ENUM_ALIAS(mocha_pixel_int, "int");
	MOCHA_ENUM_ALIAS(mocha_pixel_uint, "uint");
	MOCHA_ENUM_ALIAS(mocha_pixel_float, "float");
	MOCHA_ENUM_ALIAS(mocha_pixel_double, "double");
} MOCHA_ENUM_STRING_END;

#endif

